﻿const puppeteer = require('puppeteer')
var CONFIG = require('./config.js')
const ora = require('ora')
var spinner = ora('Loading unicorns')
let number = 0, isTime = false, isTargetScore = false;
var urlList = [],
    t,
    listType = 'Document',
    pagenumber = 0,
    totalSize = 0,
    pageUrl = {
        Document: 'DocumentKnowledge',
        Video: 'VideoKnowledge'
    }
const goFn = async () => {
    global.browser = await puppeteer.launch({
        defaultViewport: {
            width: 1400,
            height: 930
        },
        timeout: 0, //timeout here is 无限制
        args: ['--disable-bundled-ppapi-flash=true'],
        // devtools: true,
        // headless: false
        headless: true
    })
    global.page = CONFIG.PAGE;
    spinner.text = `正在登陆`
    spinner.start()
    const login = await browser.newPage()
    await login.goto(CONFIG.LOGINURL)
    await doLogin(login)
}
const goList = async () => {
    spinner.stop()
    spinner.text = `正在跳转至第${global.page}页`
    spinner.start()
    const resUrl = CONFIG.BRUSHONLINECLASSESLISTURL + `?t=${pageUrl[listType]}&ps=50&pi=` + global.page;
    await global.list.goto(
        resUrl
    )
    await doList(list)
}
const doLogin = async (login, config) => {
    const loginForm = await login.$('#dvUserNameLoginPanel')
    const usernameLo = await loginForm.$('#txtUserName2');
    await usernameLo.type(CONFIG.USERNAME, {delay: 20});
    const passwordLo = await loginForm.$('#txtPassword2');
    await passwordLo.type(CONFIG.PASSWORD, {delay: 20});
    await loginForm.$eval('#chkloginpass', (loginBtn) => loginBtn.click())
    await loginForm.$eval('#btnLogin2', (loginBtn) => loginBtn.click())
    global.list = await global.browser.newPage()
    spinner.stop()
    await global.list.goto(CONFIG.BRUSHONLINECLASSESLISTURL + `?t=${pageUrl[listType]}&ps=50&pi=` + global.page);
    const useName = await global.list.$$eval('#divaccount > div.accountblick > span:nth-child(2)', elements => elements.map(el => el.innerText))
    if (useName == undefined || useName == null || useName.length <= 0) {
        spinner.stopAndPersist({
            symbol: `×`,
            text: `登录失败 用户名密码错误 或者需要输入验证码。如果需要输入验证码 请手动登录后重启脚本`
        })
        return
    }
    try {
        await global.list.$eval(".text-primary", el => el.click())
        spinner.stop();
        console.log("跳过移动端下载检测")
    } catch (e) {

    }
    console.log(`当前登陆用户 ${useName}`)
    spinner.start();
    setTimeout(async () => {
        await goList()
    }, 2000)
}
const doList = async (list) => {
    const listDiv = await list.$('.el-kng-img-list')
    if (!listDiv) {
        spinner.stop()
        console.log("获取列表失败")
        return
    }
    pagenumber = await list.evaluate(() => {
        let list = [...document.querySelectorAll('.pagenumber')]
        return list[list.length - 1].innerText
    })
    urlList = await list.$$eval('.el-placehold-body', nodes => nodes.map(v => {
        let flag = v.getAttribute('onclick');
        if (flag != null) {
            return `http://edu.piesat.cn` + flag.split("'")[1];
        }
    }))
    let size = urlList.length;
    let resList = new Array()
    for (let i = 0; i < size; i++) {
        let selector = `.el-kng-img-list.clearfix > li:nth-child(${i + 1}) > div:nth-child(1)>span`
        let span;
        try {
            span = await list.$eval(selector, el => el.innerText);
        } catch (e) {
        }
        if (span != '已完成') {
            resList.push(urlList[i])
        }
    }
    spinner.stop()
    console.log(`第${global.page}页，一共${size}篇文章，已读${size - resList.length}篇，未读${resList.length}篇`)
    spinner.start();
    number = size - resList.length;
    totalSize = size;
    await eval(`get${listType}Page(resList)`)
}
const jumpTesting = async (datePage) => {
    try {
        let isTips, isTips2
        isTips = await datePage.$("#dvHeartTip")
        if (isTips != null) {
            //继续学习
            spinner.text = "正在学习其他文档，继续学习当前文档"
            setTimeout(async () => {
                try {
                    await datePage.$eval("#dvHeartTip > input:nth-child(5)", bu => bu.click())
                } catch (e) {
                }
            }, 3000)
        }
        isTips2 = await datePage.$("#dvWarningView")
        if (isTips2 != null) {
            spinner.stop();
            spinner.text = "跳过检测提示"
            setTimeout(async () => {
                try {
                    await datePage.$eval("#reStartStudy", bu => bu.click())
                } catch (e) {
                }
            }, 3000)
        }
    } catch (e) {

    }
}
const learnPage = async (datePage, list) => {
    try {
        if (isTargetScore == true) {
            datePage.close();
            return;
        }
        spinner.start()
        //完成度
        let learningDegree = await datePage.evaluate(() => {
            return $('#ScheduleText').text()
        })
        //时间
        let times = await datePage.evaluate(() => {
            return $('#spanLeavTimes').text()
        })
        //判断是否提示
        jumpTesting(datePage);
        let flag = learningDegree == "100%"
        if (flag) {
            await datePage.close()
            getDocumentPage(list)
            isTime = false;
            return
        } else {
            let titleName = await datePage.$eval("#lblTitle", el => el.innerText);
            spinner.text = `当前第${global.page}页,共${pagenumber}页,已读${number}篇文档,共${totalSize}篇文档 \n正在学习：${titleName} 剩余时间：${times}}`
            let time1 = 0;
            if (isTime == false) {
                let millTime = times.match(/\d+(.\d+)?/g)
                if (millTime.length == 1) {
                    time1 = parseInt(millTime[0]);
                } else if (millTime.length == 2) {
                    time1 = parseInt(millTime[0]) * 60 + parseInt(millTime[1]);
                } else {
                    time1 = 999999999;
                }
                if (time1 >= CONFIG.MAXLEARNTIME * 60) {
                    spinner.stop();
                    console.log(`学习时间大于${CONFIG.MAXLEARNTIME}分钟，跳过该文档：${titleName}`)
                    spinner.start();
                    await datePage.close()
                    getDocumentPage(list)
                    isTime = false;
                    return
                }
                if (time1 != 0) {
                    isTime = true;
                }
            }
            let waitTime = 20000;
            if (isTime == false && time1 == 0) {
                waitTime = 2000;
            }
            t = await setTimeout(async () => {
                learnPage(datePage, list);
            }, waitTime)
        }
    } catch (e) {
        spinner.stop()
        console.log("获取元素错误")
        spinner.start();
        setTimeout(()=>learnPage(datePage, list),2000);
    }
}
const isArrivedTarget = async () => {
    await global.list.reload({
        timeout: 60000 //timeout here is 60 seconds
    })
    const spanTexts = await global.list.$$eval('#UserDayPoint1', elements => elements.map(el => el.innerText))
    if (spanTexts != undefined && spanTexts >= CONFIG.TARGETSCORE) {
        spinner.stopAndPersist({
            symbol: `√`,
            text: `以达到当日积分目标${CONFIG.TARGETSCORE}分 结束刷课!`
        })
        browser.close;
        isTargetScore = true;
        return true;
    } else {
        spinner.stop()
        console.log(`今日已学习${spanTexts}分`)
        spinner.start();
        return false;
    }
    return false;
}
const getDocumentPage = async (list) => {
    try {
        isArrivedTarget();
        if (isTargetScore == true) {
            return;
        }
        t && clearTimeout(t)
        if (list.length == 0) {
            global.page++;
            number = 0;
            goList()
            spinner.stop()
            return
        }
        let datePage = await global.browser.newPage()
        let url = list.shift()
        if (!url || typeof url != 'string') {
            await datePage.close()
            await getDocumentPage(list)
            return
        }
        await datePage.goto(url, {
            timeout: 60000 //timeout here is 60 seconds
        })
        number++
        learnPage(datePage, list);
    } catch (err) {
        console.log(err)
    }
}
module.exports = goFn
